package com.itheima.stock.Thread;

/*
安全问题出现的条件
是多线程环境
有共享数据
有多条语句操作共享数据
如何解决多线程安全问题呢?

基本思想：让程序没有安全问题的环境
怎么实现呢?

把多条语句操作共享数据的代码给锁起来，让任意时刻只能有一个线程执行即可
Java提供了同步代码块的方式来解决

同步代码块格式：

synchronized(任意对象) {
多条语句操作共享数据的代码
}
synchronized(任意对象)：就相当于给代码加锁了，任意对象就可以看成是一把锁

同步的好处和弊端

好处：解决了多线程的数据安全问题

弊端：当线程很多时，因为每个线程都会去判断同步上的锁，这是很耗费资源的，无形中会降低程序的运行效率
 */
public class Synchronnized {
    public static void main(String[] args) {
        //无加锁状态
        // 线程不安全 会出现多人买到同一张票 或者 票数不对情况
        // 耗时5555ms

//        MyThread myThread = new MyThread();
//        Thread t1 = new Thread(myThread, "窗口1");
//        Thread t2 = new Thread(myThread, "窗口2");
//        t1.start();
//        t2.start();


        //有加锁状态
        //加锁后，线程安全，票数正确
        //耗时10921ms
        MyThread2 mS = new MyThread2();
        Thread t3 = new Thread(mS, "窗口1");
        Thread t4 = new Thread(mS, "窗口2");
        t3.start();
        t4.start();

    }

    public static class MyThread implements Runnable {
        private int tickets = 100;


        public void run() {
            long start1 = System.currentTimeMillis();
            while (true) {
                //synchronized (MyThread.class) {
                if (tickets > 0) {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    tickets--;
                    System.out.println(Thread.currentThread().getName() + "买的第" + tickets + "张票");
                } else {
                    break;
                }
                //}
            }
            System.out.println("程序运行时间：" + (System.currentTimeMillis() - start1));
        }

    }

    public static class MyThread2 implements Runnable {
        private int tickets = 100;

        public void run() {
            long start1 = System.currentTimeMillis();
            while (true) {
                synchronized (MyThread.class) { //代码运行到这会加锁
                    if (tickets > 0) {
                        try {
                            Thread.sleep(100);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        tickets--;
                        System.out.println(Thread.currentThread().getName() + "买的第" + tickets + "张票");
                    } else {
                        break;
                    }
                }// 代码运行到这会解锁
            }
            System.out.println("程序运行时间：" + (System.currentTimeMillis() - start1));
        }
    }
}
